
#include "OneButton.h"
#include <Wire.h> // must be included here so that Arduino library object file references work
#include <RtcDS1307.h>
#define displayGroupNumber 6
RtcDS1307<TwoWire> Rtc(Wire);
#include <LiquidCrystal_I2C.h>
// Set the LCD address to 0x27 for a 16 chars and 2 line display
LiquidCrystal_I2C lcd(0x27, 16, 2);
// Setup a new OneButton on pin A1.
OneButton button1(A1, !true);
// Setup a new OneButton on pin A2.
OneButton button2(A2, !true);
// Setup a new OneButton on pin A3.
OneButton button3(A3, !true);
// Setup a new OneButton on pin A4.
OneButton button4(A4, !true);
#define countof(a) (sizeof(a) / sizeof(a[0]))
int showTime=1;
int data[5][7];//时，分,顿4药量，开关
int btns[4][4];
int lastBtn = 0;
int i=0;//i>=29共30个对应数据显示（0开始）+4剩药量
char show[20];
char numA;

// setup code here, to run once:
void setup() {
    // Setup the Serial port.initialize the LCD
    lcd.begin();
    Serial.begin(9600);
    Rtc.Begin();
    RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__);
    // Turn on the blacklight and print a message.
    lcd.backlight();
    while (!Serial) {
        ; // wait for serial port to connect. Needed for Leonardo only
        }
    //Serial.println("Starting TwoButtons...");

    // link the button 1 functions.
    button1.attachClick(click1);
    button1.attachDoubleClick(doubleclick1);
    button1.attachLongPressStart(longPressStart1);
    button1.attachLongPressStop(longPressStop1);
    button1.attachDuringLongPress(longPress1);

    // link the button 2 functions.
    button2.attachClick(click2);
    button2.attachDoubleClick(doubleclick2);
    button2.attachLongPressStart(longPressStart2);
    button2.attachLongPressStop(longPressStop2);
    button2.attachDuringLongPress(longPress2);

    // link the button 3 functions.
    button3.attachClick(click3);
    button3.attachDoubleClick(doubleclick3);
    button3.attachLongPressStart(longPressStart3);
    button3.attachLongPressStop(longPressStop3);
    button3.attachDuringLongPress(longPress3);

    // link the button 4 functions.
    button4.attachClick(click4);
    button4.attachDoubleClick(doubleclick4);
    button4.attachLongPressStart(longPressStart4);
    button4.attachLongPressStop(longPressStop4);
    button4.attachDuringLongPress(longPress4);

    ////////////////////////////rtc///////////////////////////////////

    // never assume the Rtc was last configured by you, so
    // just clear them to your needed state
    Rtc.SetSquareWavePin(DS1307SquareWaveOut_Low);
    lcd.setCursor(0,1);
    lcd.print(" Powered by CJH ");
    delay(3000);
    lcd.setCursor(0,1);
    lcd.print("  1.show menu   ");
    } // setup

//////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
// main code here, to run repeatedly:
void loop() {
    // keep watching the push buttons:

    button1.tick();
    button2.tick();
    button3.tick();
    button4.tick();

//////////////////////////////////////////
    getTime();

    //Serial.println();

    //delay(1000); // ten seconds

    // You can implement other code in here or just wait a while

    if(btns[0][0]==1)mainSet();
    } // loop

//////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////

void getTime() {
    if (!Rtc.IsDateTimeValid()) {
        if (Rtc.LastError() != 0) {
            // we have a communications error
            // see https://www.arduino.cc/en/Reference/WireEndTransmission for
            // what the number means
            Serial.print("RTC communications error = ");
            Serial.println(Rtc.LastError());
            }
        else {
            // Common Causes:
            //    1) the battery on the device is low or even missing and the power line was disconnected
            Serial.println("RTC lost confidence in the DateTime!");
            }
        }

    RtcDateTime now = Rtc.GetDateTime();

    printDateTime(now);
    delay(10);
    }

void clearBtns() {
    int i,j;
    for(i=0; i<4; i++) {
        for(j=0; j<4; j++) {
            btns[i][j]=0;
            }
        }
    lastBtn = 0;
    }

int waitBtns() {
    while(btns[0][0]+btns[1][0]+btns[2][0]+btns[3][0]!=1) {
        getTime();
        clearBtns();
        button1.tick();
        button2.tick();
        button3.tick();
        button4.tick();
        }
    if(btns[0][0]==1)lastBtn = 1;
    else if(btns[1][0]==1)lastBtn = 2;
    else if(btns[2][0]==1)lastBtn = 3;
    else if(btns[3][0]==1)lastBtn = 4;
    return lastBtn;
    }

void mainSet() {
    //if(btns[0][0]==1)return;
    showTime=0;
    clearBtns();
//startDisplay:
    Serial.println("menuDisplay");
    while(showTime==0) {
        getTime();
        menuDisplay();
        clearBtns();
        waitBtns();
        rollDisplay();
        }
    return;
    } // c

void menuDisplay() {
    if(i/displayGroupNumber==5) {
        switch (i%displayGroupNumber) {
            case 0:
                //当等于0时，执行一些语句
                snprintf_P(show,
                           countof(show),
                           PSTR("Pill A remain - %01u"),
                           numA);
                break;
            case 1:
                //当等于1时，执行一些语句
                snprintf_P(show,
                           countof(show),
                           PSTR("Pill B remain - %01u"),
                           numA);
                break;
            case 2:
                //当等于2时，执行一些语句
                snprintf_P(show,
                           countof(show),
                           PSTR("Pill C remain - %01u"),
                           numA);
                break;
            case 3:
                //当等于3时，执行一些语句
                snprintf_P(show,
                           countof(show),
                           PSTR("Pill D remain - %01u"),
                           numA);
                break;
                //default:
            }
        }
    else {
        switch (i%displayGroupNumber) {
            case 0:
                //当等于0时，执行一些语句
                displayTimeSet();
                break;
            case 5:
                //当等于0时，执行一些语句
                displaySwitch();
                break;
            default:
                //如果没有任何匹配，执行default
                //default可有可不有
                displayPillNum();
                // lastBtn=0;
            }
        }
    }

void rollDisplay() {
    switch (lastBtn) {
        case 1:
            //当等于1时，执行一些语句
            showTime=1;
            clearBtns();
            return;
            break;
        case 2:
            //当等于2时，执行一些语句
            switch (i%displayGroupNumber) {
                case 0:
                    //当等于0时，执行一些语句
                    setAlarmTime();
                    break;
                case 5:
                    //当等于0时，执行一些语句
                    setSwitch();
                    break;
                default:
                    setPillNum();
                    break;
                }

            break;
        case 3:
            //当等于3时，执行一些语句
            if(i>0)i--;
            //goto startDisplay;
            //menuDisplay();
            //waitBtns();
            break;
        case 4:
            //当等于4时，执行一些语句
            if(i<33)i++;
            //goto startDisplay;
            // menuDisplay();
            //waitBtns();
            break;
        default:
            //如果没有任何匹配，执行default
            //default可有可不有
            lastBtn=0;
        }
    }

void displayTimeSet() {
    char show[20];
    snprintf_P(show,
               countof(show),
               PSTR(" %01u Time - %02u:%02u"),
               i/displayGroupNumber+1,
               data[i/displayGroupNumber][0],
               data[i/displayGroupNumber][1] );
    lcd.clear();
    lcd.home();
    lcd.print(show);
    lcd.setCursor(0,1);
    lcd.print("1Back home 2 Set");
    }

void setAlarmTime() {
    char show[20];
    clearBtns();
    lcd.setCursor(0,1);
    lcd.print("          --    ");
    while(waitBtns()!=2) {
        getTime();
        //clearBtns();
        //waitBtns();
        if(btns[2][0]==1) {
            if(data[i/displayGroupNumber][0]>0) {
                data[i/displayGroupNumber][0]--;
                }
            }
        else if(btns[3][0]==1) {
            if(data[i/displayGroupNumber][0]<23) {
                data[i/displayGroupNumber][0]++;
                }
            }
        else if(btns[0][0]==1) {
            showTime=1;
            clearBtns();
            return;
            }
        clearBtns();
        snprintf_P(show,
                   countof(show),
                   PSTR(" %01u Time - %02u:%02u"),
                   i/displayGroupNumber+1,
                   data[i/displayGroupNumber][0],
                   data[i/displayGroupNumber][1] );
        //lcd.clear();
        lcd.home();
        lcd.print(show);
        lcd.setCursor(0,1);
        lcd.print("          --    ");
        }
    //设置分钟
    clearBtns();
    lcd.setCursor(0,1);
    lcd.print("             -- ");
    while(waitBtns()!=2) {
        getTime();
        //clearBtns();
        //waitBtns();
        if(btns[2][0]==1) {
            if(data[i/displayGroupNumber][1]>0) {
                data[i/displayGroupNumber][1]-=10;
                }
            }
        else if(btns[3][0]==1) {
            if(data[i/displayGroupNumber][1]<50) {
                data[i/displayGroupNumber][1]+=10;
                }
            }
        else if(btns[0][0]==1) {
            showTime=1;
            clearBtns();
            return;
            }
        clearBtns();
        snprintf_P(show,
                   countof(show),
                   PSTR(" %01u Time - %02u:%02u"),
                   i/displayGroupNumber+1,
                   data[i/displayGroupNumber][0],
                   data[i/displayGroupNumber][1] );
        //lcd.clear();
        lcd.home();
        lcd.print(show);
        lcd.setCursor(0,1);
        lcd.print("             -- ");
        }
    }

void displayPillNum() {
    Serial.println("displayPillNum()");
    char show[20];
    switch (i%displayGroupNumber) {
        case 1:
            //当等于1时，执行一些语句
            snprintf_P(show,
                       countof(show),
                       PSTR("%01u Pill A num - %01u"),
                       i/displayGroupNumber+1,
                       data[i/displayGroupNumber][i%displayGroupNumber+1]);
            break;
        case 2:
            //当等于2时，执行一些语句
            snprintf_P(show,
                       countof(show),
                       PSTR("%01u Pill B num - %01u"),
                       i/displayGroupNumber+1,
                       data[i/displayGroupNumber][i%displayGroupNumber+1]);
            break;
        case 3:
            //当等于3时，执行一些语句
            snprintf_P(show,
                       countof(show),
                       PSTR("%01u Pill C num - %01u"),
                       i/displayGroupNumber+1,
                       data[i/displayGroupNumber][i%displayGroupNumber+1]);
            break;
        case 4:
            //当等于4时，执行一些语句
            snprintf_P(show,
                       countof(show),
                       PSTR("%01u Pill D num - %01u"),
                       i/displayGroupNumber+1,
                       data[i/displayGroupNumber][i%displayGroupNumber+1]);
            break;
        default:
            break;
        }

    lcd.clear();
    lcd.home();
    lcd.print(show);
    lcd.setCursor(0,1);
    lcd.print("1Back 2 Set");
    }

void setPillNum() {
    char show[20];
    clearBtns();
    lcd.setCursor(0,1);
    lcd.print("               -");
    while(waitBtns()!=2) {
        getTime();
        //clearBtns();
        //waitBtns();
        if(btns[2][0]==1) {
            if(data[i/displayGroupNumber][i%displayGroupNumber+1]>0) {
                data[i/displayGroupNumber][i%displayGroupNumber+1]--;
                }
            }
        else if(btns[3][0]==1) {
            //if(data[i/displayGroupNumber][2]<23) {
            data[i/displayGroupNumber][i%displayGroupNumber+1]++;
            //    }
            }
        else if(btns[0][0]==1) {
            showTime=1;
            clearBtns();
            return;
            }
        clearBtns();
        switch (i%displayGroupNumber) {
            case 1:
                //当等于1时，执行一些语句
                snprintf_P(show,
                           countof(show),
                           PSTR("%01u Pill A num - %01u"),
                           i/displayGroupNumber+1,
                           data[i/displayGroupNumber][i%displayGroupNumber+1]);
                break;
            case 2:
                //当等于2时，执行一些语句
                snprintf_P(show,
                           countof(show),
                           PSTR("%01u Pill B num - %01u"),
                           i/displayGroupNumber+1,
                           data[i/displayGroupNumber][i%displayGroupNumber+1]);
                break;
            case 3:
                //当等于3时，执行一些语句
                snprintf_P(show,
                           countof(show),
                           PSTR("%01u Pill C num - %01u"),
                           i/displayGroupNumber+1,
                           data[i/displayGroupNumber][i%displayGroupNumber+1]);
                break;
            case 4:
                //当等于4时，执行一些语句
                snprintf_P(show,
                           countof(show),
                           PSTR("%01u Pill D num - %01u"),
                           i/displayGroupNumber+1,
                           data[i/displayGroupNumber][i%displayGroupNumber+1]);
                break;
            default:
                break;
            }
        lcd.clear();
        lcd.home();
        lcd.print(show);
        lcd.setCursor(0,1);
        lcd.print("               -");
        }
    }

void displaySwitch() {
    char show[20];
    snprintf_P(show,
               countof(show),
               PSTR(" %01u  Switch  - %01u "),
               i/displayGroupNumber+1,
               data[i/displayGroupNumber][6] );
    lcd.clear();
    lcd.home();
    lcd.print(show);
    lcd.setCursor(0,1);
    lcd.print("1Back home 2 Set");
    }

void setSwitch() {
    char show[20];
    clearBtns();
    lcd.setCursor(0,1);
    lcd.print("              - ");
    while(waitBtns()!=2) {
        getTime();
        if(btns[2][0]==1||btns[3][0]==1) {
            //if(data[i/displayGroupNumber][i/displayGroupNumber+1]>0) {
            data[i/displayGroupNumber][6]=data[i/displayGroupNumber][6]?0:1;
            // }
            }
        else if(btns[0][0]==1) {
            showTime=1;
            clearBtns();
            return;
            }
        clearBtns();
        snprintf_P(show,
                   countof(show),
                   PSTR(" %01u  Switch  - %01u "),
                   i/displayGroupNumber+1,
                   data[i/displayGroupNumber][6] );
        lcd.clear();
        lcd.home();
        lcd.print(show);
        lcd.setCursor(0,1);
        lcd.print("              - ");
        }
    }


void printDateTime(const RtcDateTime& dt) {
    char timestring[20];
    data[0][0]=21;
    data[0][1]=20;
    data[0][6]=1;
    snprintf_P(timestring,
               countof(timestring),
               PSTR(" %02u/%02u %02u:%02u:%02u "),
               dt.Month(),
               dt.Day(),
               //dt.Year(),
               dt.Hour(),
               dt.Minute(),
               dt.Second() );
    /*PSTR("%02u/%02u/%04u %02u:%02u:%02u"),
    dt.Month(),
    dt.Day(),
    dt.Year(),
    dt.Hour(),
    dt.Minute(),
    dt.Second() );*/
    char a;
    for(a=0; a<5; a++) {
        if(data[a][6]==1) {
            if(data[a][0]==dt.Hour()) {
                if(data[a][1]==dt.Minute()) {
                    //到时操作
                    snprintf_P(show,
                               countof(show),
                               PSTR("Now %01u Time-%02u:%02u"),
                               a+1,
                               data[a][0],
                               data[a][1] );
                    lcd.clear();
                    lcd.home();
                    lcd.print(show);
                    lcd.setCursor(0,1);
                    snprintf_P(show,
                               countof(show),
                               PSTR("A%02u B%02u C%02u D%02u "),
                               data[a][2],
                               data[a][3],
                               data[a][4],
                               data[a][5] );
                    lcd.print(show);
                    while(1) {
                        Serial.print("!!!!!!!");
                        }
                    }
                }
            }
        }
    if(showTime==1) {
        lcd.home();
        //lcd.setCursor(0,1);
        lcd.print(timestring);
        lcd.setCursor(0,1);
        lcd.print("  1.show menu   ");
        //lcd.print(dt.Second());
        //Serial.println(dt.Second());
        }
    }

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ----- button 1 callback functions

// This function will be called when the button1 was pressed 1 time (and no 2. button press followed).
void click1() {
    //Serial.println("Button 1 click.");
    btns[0][0]=1;
    //lastBtn = 1;
    } // click1


// This function will be called when the button1 was pressed 2 times in a short timeframe.
void doubleclick1() {
    Serial.println("Button 1 doubleclick.");
    } // doubleclick1


// This function will be called once, when the button1 is pressed for a long time.
void longPressStart1() {
    Serial.println("Button 1 longPress start");
    } // longPressStart1


// This function will be called often, while the button1 is pressed for a long time.
void longPress1() {
    Serial.println("Button 1 longPress...");
    } // longPress1


// This function will be called once, when the button1 is released after beeing pressed for a long time.
void longPressStop1() {
    Serial.println("Button 1 longPress stop");
    } // longPressStop1

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ... and the same for button 2:

void click2() {
    btns[1][0]=1;
    //lastBtn = 2;
    //Serial.println("Button 2 click.");
    } // click2


void doubleclick2() {
    Serial.println("Button 2 doubleclick.");
    } // doubleclick2


void longPressStart2() {
    Serial.println("Button 2 longPress start");
    } // longPressStart2


void longPress2() {
    Serial.println("Button 2 longPress...");
    } // longPress2

void longPressStop2() {
    Serial.println("Button 2 longPress stop");
    } // longPressStop2

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ----- button 3 callback functions

// This function will be called when the button3 was pressed 3 time (and no 4. button press followed).
void click3() {
    btns[2][0]=1;
    // lastBtn = 3;
    Serial.println("Button 3 click.");
    } // click3


// This function will be called when the button3 was pressed 4 times in a short timeframe.
void doubleclick3() {
    Serial.println("Button 3 doubleclick.");
    } // doubleclick3


// This function will be called once, when the button3 is pressed for a long time.
void longPressStart3() {
    Serial.println("Button 3 longPress start");
    } // longPressStart3


// This function will be called often, while the button3 is pressed for a long time.
void longPress3() {
    Serial.println("Button 3 longPress...");
    } // longPress3


// This function will be called once, when the button3 is released after beeing pressed for a long time.
void longPressStop3() {
    Serial.println("Button 3 longPress stop");
    } // longPressStop3

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ... and the same for button 4:

void click4() {
    Serial.println("Button 4 click.");
    //lastBtn = 4;
    btns[3][0]=1;
    } // click4


void doubleclick4() {

    Serial.println("Button 4 doubleclick.");
    } // doubleclick4


void longPressStart4() {
    Serial.println("Button 4 longPress start");
    } // longPressStart4


void longPress4() {
    Serial.println("Button 4 longPress...");
    } // longPress4

void longPressStop4() {
    Serial.println("Button 4 longPress stop");
    } // longPressStop4

